/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    unused_variables,
    clippy::never_loop
)]

use crate::common::*;

extern "C" {
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    fn __ctype_b_loc() -> *mut *const libc::c_ushort;
    fn strrchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
    fn read(__fd: libc::c_int, __buf: *mut libc::c_void, __nbytes: size_t) -> ssize_t;
    fn close(__fd: libc::c_int) -> libc::c_int;
    fn sysconf(__name: libc::c_int) -> libc::c_long;
    fn __errno_location() -> *mut libc::c_int;
    fn snprintf(
        _: *mut libc::c_char,
        _: libc::c_ulong,
        _: *const libc::c_char,
        _: ...
    ) -> libc::c_int;
    fn open(__file: *const libc::c_char, __oflag: libc::c_int, _: ...) -> libc::c_int;

    fn strtoull(
        _: *const libc::c_char,
        _: *mut *mut libc::c_char,
        _: libc::c_int,
    ) -> libc::c_ulonglong;
    fn memchr(_: *const libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void;

    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
}

pub type __ssize_t = libc::c_long;
pub const PATH_MAX: libc::c_int = 4096;
pub const _SC_CLK_TCK: libc::c_int = 2;
pub const O_NOFOLLOW: libc::c_int = 131072;
pub const O_RDONLY: libc::c_int = 0;
pub const EINVAL: libc::c_int = 22;
pub const LLONG_MAX: libc::c_longlong = 9223372036854775807;
pub const EINTR: libc::c_int = 4;

#[no_mangle]
pub fn get_starttime(mut pid: pid_t, mut starttime: *mut timespec) -> libc::c_int {
    let mut current_block: u64;
    let mut path: [libc::c_char; 4096] = [0; 4096];
    let mut cp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut buf: [libc::c_char; 1024] = [0; 1024];
    let mut nread: ssize_t = 0;
    let mut ret: libc::c_int = -(1 as libc::c_int);
    let mut fd: libc::c_int = -(1 as libc::c_int);
    let mut tps: libc::c_long = 0;
    unsafe {
        let sudo_debug_subsys_1: libc::c_int = *sudoers_subsystem_ids
            .as_mut_ptr()
            .offset(17 as libc::c_int as isize)
            as libc::c_int;
        debug_decl!(SUDOERS_DEBUG_LDAP!());

        tps = sysconf(_SC_CLK_TCK);

        'done: loop {
            if tps == -1 {
                break 'done;
            }

            snprintf(
                path.as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 4096]>() as libc::c_ulong,
                b"/proc/%u/stat\0" as *const u8 as *const libc::c_char,
                pid as libc::c_uint,
            );
            fd = open(
                path.as_mut_ptr(),
                O_RDONLY as libc::c_int | O_NOFOLLOW as libc::c_int,
            );
            if fd != -1 {
                cp = buf.as_mut_ptr();
                nread = read(
                    fd,
                    cp as *mut libc::c_void,
                    buf.as_mut_ptr()
                        .offset(
                            ::std::mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong as isize,
                        )
                        .offset_from(cp) as libc::c_long as size_t,
                );
                while nread != 0 {
                    if nread == -1 {
                        if *__errno_location() == EAGAIN || *__errno_location() == EINTR {
                            nread = read(
                                fd,
                                cp as *mut libc::c_void,
                                buf.as_mut_ptr()
                                    .offset(::std::mem::size_of::<[libc::c_char; 1024]>()
                                        as libc::c_ulong
                                        as isize)
                                    .offset_from(cp) as libc::c_long
                                    as size_t,
                            );
                            continue;
                        }
                        break;
                    }
                    cp = cp.offset(nread as isize);

                    if cp
                        >= buf
                            .as_mut_ptr()
                            .offset(
                                ::std::mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong
                                    as isize,
                            )
                    {
                        break;
                    }
                    nread = read(
                        fd,
                        cp as *mut libc::c_void,
                        buf.as_mut_ptr()
                            .offset(
                                ::std::mem::size_of::<[libc::c_char; 1024]>() as libc::c_ulong
                                    as isize,
                            )
                            .offset_from(cp) as libc::c_long as size_t,
                    );
                } // while nread != 0

                if nread == 0 as libc::c_int as libc::c_long
                    && (memchr(
                        buf.as_mut_ptr() as *const libc::c_void,
                        '\u{0}' as i32,
                        cp.offset_from(buf.as_mut_ptr()) as libc::c_long as libc::c_ulong,
                    ))
                    .is_null()
                {
                    *cp = '\u{0}' as i32 as libc::c_char;
                    cp = strrchr(buf.as_mut_ptr(), ')' as i32);

                    if !cp.is_null() {
                        let mut ep: *mut libc::c_char = cp;
                        let mut field: libc::c_int = 1 as libc::c_int;

                        loop {
                            ep = ep.offset(1);
                            if *ep as libc::c_int == '\u{0}' as i32 {
                                break;
                            }
                            if *ep as libc::c_int == ' ' as i32 {
                                field += 1;
                                if field == 22 as libc::c_int {
                                    let mut ullval: libc::c_ulonglong = 0;
                                    if *(*__ctype_b_loc())
                                        .offset(*cp as libc::c_uchar as libc::c_int as isize)
                                        as libc::c_int
                                        & _ISdigit as libc::c_int as libc::c_ushort as libc::c_int
                                        == 0
                                    {
                                        *__errno_location() = EINVAL;
                                        break 'done;
                                    }
                                    *__errno_location() = 0 as libc::c_int;
                                    ullval = strtoull(cp, &mut ep, 10 as libc::c_int);
                                    if ep == cp || *ep as libc::c_int != ' ' as i32 {
                                        *__errno_location() = EINVAL as libc::c_int;
                                        break 'done;
                                    }
                                    if *__errno_location() == ERANGE as libc::c_int
                                        && ullval
                                            == (LLONG_MAX as libc::c_longlong as libc::c_ulonglong)
                                                .wrapping_mul(2 as libc::c_ulonglong)
                                                .wrapping_add(1 as libc::c_ulonglong)
                                    {
                                        break 'done;
                                    }

                                    (*starttime).tv_sec =
                                        ullval.wrapping_div(tps as libc::c_ulonglong) as __time_t;
                                    (*starttime).tv_nsec =
                                        ullval.wrapping_rem(tps as libc::c_ulonglong).wrapping_mul(
                                            (1000000000 as libc::c_int as libc::c_long / tps)
                                                as libc::c_ulonglong,
                                        )
                                            as __syscall_slong_t;
                                    ret = 0 as libc::c_int;

                                    sudo_debug_printf2_v1(
                                        get_function_name!(),
                                        get_file_name!(),
                                        line!() as libc::c_int,
                                        SUDO_DEBUG_INFO | sudo_debug_subsys_1 as libc::c_int,
                                        b"%s: start time for %d: { %lld, %ld }\0" as *const u8
                                            as *const libc::c_char,
                                        get_function_name!(),
                                        pid,
                                        (*starttime).tv_sec,
                                        (*starttime).tv_nsec,
                                    );
                                    break 'done;
                                }
                                cp = ep.offset(1);
                            } //ep = ' '
                        } //loop
                    } //same as !cp.is_null
                } //same as nread == 0 && ..
            }
            *__errno_location() = ENOENT;

            break 'done;
        }
        if fd != -1 {
            close(fd);
        }
        if ret == -1 {
            sudo_debug_printf2_v1(
                get_function_name!(),
                get_file_name!(),
                line!() as libc::c_int,
                SUDO_DEBUG_ERROR
                    | SUDO_DEBUG_LINENO
                    | SUDO_DEBUG_ERRNO
                    | sudo_debug_subsys_1 as libc::c_int,
                b"unable to get start time for %d via %s\0" as *const u8 as *const libc::c_char,
                pid as libc::c_int,
                path,
            );
        }
        debug_return_int!(ret);
    } //unsafe
}
